#include "morphology.h"
#include <flgrCoreTypes.h>
#include <flgrCoreErrors.h>
#include <flgrCoreData.h>
#include <flgrCoreCopy.h>
#include <flgrCoreChannel.h>
#include <flgrImageIO.h>
#include <flgrCoreDataIO.h>
#include <flgrMorphoHoM.h>
#include <flgrMorphoGolay.h>
#include <flgrCoreCompare.h>
#include <flgrMorphoLabel.h>
#include <flgrArith.h>
#include "externtypes.h"
#include "types.h"
#include "core.h"
#include <stack>

using namespace std;

Binary_Image* flgr2dtoBinary(FLGR_Data2D* img){

    if(img->spp>1)
        return NULL;
    Binary_Image* out = new Binary_Image(img->size_y,img->size_x);
    switch((int)img->type){
        case 0:
        {
            fgBIT** pixmap = (fgBIT**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=pixmap[i][j];
                }
            break;
        }
        case 1:
        {
            fgUINT8** pixmap = (fgUINT8**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 2:
        {
            fgUINT16** pixmap = (fgUINT16**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 3:
        {
            fgUINT32** pixmap = (fgUINT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 4:
        {
            fgUINT64** pixmap = (fgUINT64**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 5:
        {
            fgINT8** pixmap = (fgINT8**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 6:
        {
            fgINT16** pixmap = (fgINT16**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 7:
        {
            fgINT32** pixmap = (fgINT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 8:
        {
            fgINT64** pixmap = (fgINT64**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 9:
        {
            fgFLOAT32** pixmap = (fgFLOAT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        case 10:
        {
            fgFLOAT64** pixmap = (fgFLOAT64**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(pixmap[i][j]>0);
                }
            break;
        }
        default:
            return NULL;
    }

    return out;
}

Grey_Image* flgr2dtoGrey(FLGR_Data2D* img){
   if(img->spp>1)
        return NULL;
    Grey_Image* out = new Grey_Image(img->size_y,img->size_x,(unsigned int)~0);
    switch((int)img->type){
        case 0:
        {
            fgBIT** pixmap = (fgBIT**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 1:
        {
            fgUINT8** pixmap = (fgUINT8**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 2:
        {
            fgUINT16** pixmap = (fgUINT16**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 3:
        {
            fgUINT32** pixmap = (fgUINT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 4:
            return NULL;
        case 5:
        {
            fgINT8** pixmap = (fgINT8**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 6:
        {
            fgINT16** pixmap = (fgINT16**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 7:
        {
            fgINT32** pixmap = (fgINT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 8:
            return NULL;
        case 9:
        {
            fgFLOAT32** pixmap = (fgFLOAT32**)img->array;
            for(int i=0;i<img->size_y;i++)
                for(int j=0;j<img->size_x;j++){
                    out->pixelmap[i][j]=(unsigned int)pixmap[i][j];
                }
            break;
        }
        case 10:
            return NULL;
        default:
            return NULL;
    }

    return out;
}


FLGR_Data2D* Binarytoflgr2d_UINT16(Binary_Image* img){
    if(img==NULL) return NULL;
    FLGR_Data2D* out = flgr2d_create_pixmap(img->getHeight(),img->getWidth(),1,FLGR_UINT16);
    if(out==NULL) return NULL;
    fgUINT16** pixmap = (fgUINT16**)out->array;
    for(int i=0;i<out->size_y;i++)
        for(int j=0;j<out->size_x;j++){
            pixmap[i][j]=img->pixelmap[i][j];
        }
    return out;
}

FLGR_Data2D* Binarytoflgr2d_UINT8(Binary_Image* img){
    if(img==NULL) return NULL;
    FLGR_Data2D* out = flgr2d_create_pixmap(img->getHeight(),img->getWidth(),1,FLGR_UINT8);
    if(out==NULL) return NULL;
    fgUINT8** pixmap = (fgUINT8**)out->array;
    for(int i=0;i<out->size_y;i++)
        for(int j=0;j<out->size_x;j++){
            pixmap[i][j]=(fgUINT8)img->pixelmap[i][j];
        }
    return out;
}


FLGR_Data2D* Greytoflgr2d_UINT16(Grey_Image* img){
    if(img==NULL) return NULL;
    FLGR_Data2D* out = flgr2d_create_pixmap(img->getHeight(),img->getWidth(),1,FLGR_UINT16);
    if(out==NULL) return NULL;
    fgUINT16** pixmap = (fgUINT16**)out->array;
    for(int i=0;i<out->size_y;i++)
        for(int j=0;j<out->size_x;j++){
            pixmap[i][j]=(fgUINT16)img->pixelmap[i][j];
        }
    return out;
}

StructuringElement::StructuringElement(int height, int width,Position center,Shape shape) : Binary_Image(height,width){
        this->center=center;
        FLGR_Data2D* draw;
        Binary_Image* temp;
        switch(shape){
            case NONE:
                return;
            case DISK:
                draw = flgr2d_create_neighborhood(height,width,1,FLGR_UINT16,FLGR_DISC,FLGR_8_CONNEX);
                break;
            case CROSS1:
                draw = flgr2d_create_neighborhood(height,width,1,FLGR_UINT16,FLGR_CROSS,FLGR_8_CONNEX);
                break;
            case CROSS2:
                draw = flgr2d_create_neighborhood(height,width,1,FLGR_UINT16,FLGR_CROSSX,FLGR_8_CONNEX);
                break;
            case RECTANGLE:
                draw = flgr2d_create_neighborhood(height,width,1,FLGR_UINT16,FLGR_RECT,FLGR_8_CONNEX);
                break;
            case ELLIPSE:
                draw = flgr2d_create_neighborhood(height,width,1,FLGR_UINT16,FLGR_ELLIPSE,FLGR_8_CONNEX);
                break;
            default:
                return;
        }
        temp = flgr2dtoBinary(draw);
        for(int i=0;i<height;i++)
                for(int j=0;j<width;j++){
                    this->pixelmap[i][j]=temp->pixelmap[i][j];
                }
        delete temp;
}


Grey_Image* MOperator::erosion(Grey_Image* image,Grey_Image* out,StructuringElement* se){
    unsigned int i,j,k,l;
    unsigned int max=image->getGreyLevels()+1,min,product;

    if(out==NULL)
        out = new Grey_Image(image->getHeight(),image->getWidth(),image->getGreyLevels());


    /*Expand borders*/
    Grey_Image* out_temp = new Grey_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth(),image->getGreyLevels());
    Grey_Image* temp = new Grey_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth(),image->getGreyLevels());
    for(i=0;i<image->getHeight();i++)
        for(j=0;j<image->getWidth();j++)
            temp->pixelmap[i+se->getHeight()][j+se->getWidth()]=image->pixelmap[i][j];

    /*erosion*/
    /*For all pixels*/
    for(i=0;i<image->getHeight()+se->getHeight();i++)
        for(j=0;j<image->getWidth()+se->getWidth();j++)
        {
            min=max;
            /*For all intersection with ES*/
            for(k=0;k<se->getHeight();k++)
                for(l=0;l<se->getWidth();l++){
                    /*if is a part of ES*/
                    if(se->pixelmap[k][l]){
                        /*do product*/
                        product=temp->pixelmap[i+k][j+l];
                        /*atualize minimum*/
                        if(product<min)min=product;
                    }
                }
            out_temp->setPixel(j+se->center.y,i+se->center.x,min);
        }

    /*make output image*/
    for(i=0;(i<out->getHeight() && (i+se->getHeight())<out_temp->getHeight());i++)
        for(j=0;(j<out->getWidth() && (j+se->getWidth())<out_temp->getWidth());j++)
            out->pixelmap[i][j]=out_temp->pixelmap[i+se->getHeight()][j+se->getWidth()];


    delete temp;
    delete out_temp;
    return out;
}

Grey_Image* MOperator::dilation(Grey_Image* image,Grey_Image* out,StructuringElement* se){
    unsigned int i,j,k,l;
    unsigned int max,product;

    if(out==NULL)
        out = new Grey_Image(image->getHeight(),image->getWidth(),image->getGreyLevels());

    /*Expand borders*/
    Grey_Image* out_temp = new Grey_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth(),image->getGreyLevels());
    Grey_Image* temp = new Grey_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth(),image->getGreyLevels());
    for(i=0;i<image->getHeight();i++)
        for(j=0;j<image->getWidth();j++)
            temp->pixelmap[i+se->getHeight()][j+se->getWidth()]=image->pixelmap[i][j];

    /*erosion*/
    /*For all pixels*/
    for(i=0;i<image->getHeight()+se->getHeight();i++)
        for(j=0;j<image->getWidth()+se->getWidth();j++)
        {
            max=0;
            /*For all intersection with ES*/
            for(k=0;k<se->getHeight();k++)
                for(l=0;l<se->getWidth();l++){
                    product=se->pixelmap[k][l]*temp->pixelmap[i+k][j+l];
                    /*atualize maximum*/
                    if(product>max)max=product;
                }
            out_temp->setPixel(j+se->center.y,i+se->center.x,max);
        }

    /*make output image*/
    for(i=0;(i<out->getHeight() && (i+se->getHeight())<out_temp->getHeight());i++)
        for(j=0;(j<out->getWidth() && (j+se->getWidth())<out_temp->getWidth());j++)
            out->pixelmap[i][j]=out_temp->pixelmap[i+se->getHeight()][j+se->getWidth()];


    delete temp;
    delete out_temp;
    return out;
}

//For binary

Binary_Image* MOperator::erosion(Binary_Image* image,Binary_Image* out,StructuringElement* se){
    unsigned int i,j,k,l;
    bool min;

    if(out==NULL)
        out = new Binary_Image(image->getHeight(),image->getWidth());


    /*Expand borders*/
    Binary_Image* out_temp = new Binary_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth());
    Binary_Image* temp = new Binary_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth());
    for(i=0;i<image->getHeight();i++)
        for(j=0;j<image->getWidth();j++)
            temp->pixelmap[i+se->getHeight()][j+se->getWidth()]=image->pixelmap[i][j];

    /*erosion*/
    /*For all pixels*/
    for(i=0;i<image->getHeight()+se->getHeight();i++)
        for(j=0;j<image->getWidth()+se->getWidth();j++)
        {
            min=true;
            /*For all intersection with ES*/
            for(k=0;k<se->getHeight();k++)
                for(l=0;l<se->getWidth();l++){
                    /*if is a part of ES*/
                    if(se->pixelmap[k][l]){
                        /*atualize minimum*/
                        if(temp->pixelmap[i+k][j+l]==false){
                        min=false;
                        k=se->getHeight()+1;
                        break;
                        }
                    }
                }
            out_temp->setPixel(j+se->center.y,i+se->center.x,min);
        }

    /*make output image*/
    for(i=0;(i<out->getHeight() && (i+se->getHeight())<out_temp->getHeight());i++)
        for(j=0;(j<out->getWidth() && (j+se->getWidth())<out_temp->getWidth());j++)
            out->pixelmap[i][j]=out_temp->pixelmap[i+se->getHeight()][j+se->getWidth()];


    delete temp;
    delete out_temp;
    return out;
}

Binary_Image* MOperator::dilation(Binary_Image* image,Binary_Image* out,StructuringElement* se){
    unsigned int i,j,k,l;
    bool max;

    if(out==NULL)
        out = new Binary_Image(image->getHeight(),image->getWidth());

    /*Expand borders*/
    Binary_Image* out_temp = new Binary_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth());
    Binary_Image* temp = new Binary_Image(image->getHeight()+2*se->getHeight(),image->getWidth()+2*se->getWidth());
    for(i=0;i<image->getHeight();i++)
        for(j=0;j<image->getWidth();j++)
            temp->pixelmap[i+se->getHeight()][j+se->getWidth()]=image->pixelmap[i][j];

    /*erosion*/
    /*For all pixels*/
    for(i=0;i<image->getHeight()+se->getHeight();i++)
        for(j=0;j<image->getWidth()+se->getWidth();j++)
        {
            max=false;
            /*For all intersection with ES*/
            for(k=0;k<se->getHeight();k++)
                for(l=0;l<se->getWidth();l++){
                    /*atualize maximum*/
                    if(se->pixelmap[k][l]&&temp->pixelmap[i+k][j+l]){
                    max=true;
                    k=se->getHeight()+1;
                    break;
                    }
                }
            out_temp->setPixel(j+se->center.y,i+se->center.x,max);
        }

    /*make output image*/
    for(i=0;(i<out->getHeight() && (i+se->getHeight())<out_temp->getHeight());i++)
        for(j=0;(j<out->getWidth() && (j+se->getWidth())<out_temp->getWidth());j++)
            out->pixelmap[i][j]=out_temp->pixelmap[i+se->getHeight()][j+se->getWidth()];


    delete temp;
    delete out_temp;
    return out;
}

Grey_Image* MOperator::thinning(Grey_Image* image,Grey_Image* out,StructuringElement* foreground,StructuringElement* background){
    unsigned int width,height;
    Grey_Image* temp;
    FLGR_Data2D* dest;
    FLGR_Data2D* se;
    fgUINT16** img;
    fgUINT16 pixel;
    FLGR_Data2D* flgrtemp;

    if(image==NULL || foreground==NULL || background ==NULL)
        return NULL;


    if(foreground->getHeight()>background->getHeight())
        height=foreground->getHeight();
    else
        height=background->getHeight();

    if(foreground->getWidth()>background->getWidth())
        width=foreground->getWidth();
    else
        width=background->getWidth();

    se = flgr2d_create_pixmap(height,width,1,FLGR_UINT16);
    img=(fgUINT16**)se->array;
    se->connexity=FLGR_8_CONNEX;

    for(unsigned int i=0;i<height;i++)
        for(unsigned int j=0;j<width;j++){
            if(foreground->getPixel(j,i))
                if(background->getPixel(j,i))
                    pixel=0;
                else
                    pixel=2;
            else
                if(background->getPixel(j,i))
                    pixel=1;
                else
                    pixel=0;
            img[i][j]=pixel;
        }

    dest = Greytoflgr2d_UINT16(image);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    flgr2d_thinning(flgrtemp,dest,se);

    temp = flgr2dtoGrey(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }

}
Binary_Image* MOperator::thinning(Binary_Image* image,Binary_Image* out,StructuringElement* foreground,StructuringElement* background){
    unsigned int width,height;
    Binary_Image* temp;
    FLGR_Data2D* dest;
    FLGR_Data2D* se;
    fgUINT16** img;
    fgUINT16 pixel;
    FLGR_Data2D* flgrtemp;

    if(image==NULL || foreground==NULL || background ==NULL)
        return NULL;


    if(foreground->getHeight()>background->getHeight())
        height=foreground->getHeight();
    else
        height=background->getHeight();

    if(foreground->getWidth()>background->getWidth())
        width=foreground->getWidth();
    else
        width=background->getWidth();

    se = flgr2d_create_pixmap(height,width,1,FLGR_UINT16);
    img=(fgUINT16**)se->array;
    se->connexity=FLGR_8_CONNEX;

    for(unsigned int i=0;i<height;i++)
        for(unsigned int j=0;j<width;j++){
            if(foreground->getPixel(j,i))
                if(background->getPixel(j,i))
                    pixel=0;
                else
                    pixel=2;
            else
                if(background->getPixel(j,i))
                    pixel=1;
                else
                    pixel=0;
            img[i][j]=pixel;
        }

    dest = Binarytoflgr2d_UINT16(image);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    flgr2d_thinning(flgrtemp,dest,se);

    temp = flgr2dtoBinary(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }

}

Grey_Image* MOperator::thinning_golay(Grey_Image* image,Grey_Image* out,char* golayletter){
    Grey_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Greytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay(golayletter, dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    for(int i=0;i<golay->nbse;i+=2){
        flgr2d_thinning(flgrtemp,dest,golay->se[i]);
        flgr2d_thinning(dest,flgrtemp,golay->se[i+1]);
    }

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

Binary_Image* MOperator::thinning_golay(Binary_Image* image,Binary_Image* out,char* golayletter){
    Binary_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Binarytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay(golayletter, dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    for(int i=0;i<golay->nbse;i+=2){
        flgr2d_thinning(flgrtemp,dest,golay->se[i]);
        flgr2d_thinning(dest,flgrtemp,golay->se[i+1]);
    }

    temp = flgr2dtoBinary(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

Grey_Image* MOperator::hit_or_miss_golay(Grey_Image* image,Grey_Image* out,char* golayletter,int rotation){
    Grey_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Greytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay(golayletter, dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    if(rotation<golay->nbse)
        flgr2d_hit_or_miss(flgrtemp,dest,golay->se[rotation]);


    temp = flgr2dtoGrey(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

Binary_Image* MOperator::hit_or_miss_golay(Binary_Image* image,Binary_Image* out,char* golayletter,int rotation){
    Binary_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Binarytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay(golayletter, dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    if(rotation<golay->nbse)
        flgr2d_hit_or_miss(flgrtemp,dest,golay->se[rotation]);


    temp = flgr2dtoBinary(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}




Grey_Image* MOperator::hit_or_miss(Grey_Image* image,Grey_Image* out,StructuringElement* foreground,StructuringElement* background){
    unsigned int width,height;
    Grey_Image* temp;
    FLGR_Data2D* dest;
    FLGR_Data2D* se;
    fgUINT16** img;
    fgUINT16 pixel;
    FLGR_Data2D* flgrtemp;

    if(image==NULL || foreground==NULL || background ==NULL)
        return NULL;


    if(foreground->getHeight()>background->getHeight())
        height=foreground->getHeight();
    else
        height=background->getHeight();

    if(foreground->getWidth()>background->getWidth())
        width=foreground->getWidth();
    else
        width=background->getWidth();

    se = flgr2d_create_pixmap(height,width,1,FLGR_UINT16);
    img=(fgUINT16**)se->array;
    se->connexity=FLGR_8_CONNEX;

    for(unsigned int i=0;i<height;i++)
        for(unsigned int j=0;j<width;j++){
            if(foreground->getPixel(j,i))
                if(background->getPixel(j,i))
                    pixel=0;
                else
                    pixel=2;
            else
                if(background->getPixel(j,i))
                    pixel=1;
                else
                    pixel=0;
            img[i][j]=pixel;
        }

    dest = Greytoflgr2d_UINT16(image);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    flgr2d_hit_or_miss(flgrtemp,dest,se);

    temp = flgr2dtoGrey(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }

}
Binary_Image* MOperator::hit_or_miss(Binary_Image* image,Binary_Image* out,StructuringElement* foreground,StructuringElement* background){
    unsigned int width,height;
    Binary_Image* temp;
    FLGR_Data2D* dest;
    FLGR_Data2D* se;
    fgUINT16** img;
    fgUINT16 pixel;
    FLGR_Data2D* flgrtemp;

    if(image==NULL || foreground==NULL || background ==NULL)
        return NULL;


    if(foreground->getHeight()>background->getHeight())
        height=foreground->getHeight();
    else
        height=background->getHeight();

    if(foreground->getWidth()>background->getWidth())
        width=foreground->getWidth();
    else
        width=background->getWidth();

    se = flgr2d_create_pixmap(height,width,1,FLGR_UINT16);
    img=(fgUINT16**)se->array;
    se->connexity=FLGR_8_CONNEX;

    for(unsigned int i=0;i<height;i++)
        for(unsigned int j=0;j<width;j++){
            if(foreground->getPixel(j,i))
                if(background->getPixel(j,i))
                    pixel=0;
                else
                    pixel=2;
            else
                if(background->getPixel(j,i))
                    pixel=1;
                else
                    pixel=0;
            img[i][j]=pixel;
        }

    dest = Binarytoflgr2d_UINT16(image);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    flgr2d_hit_or_miss(flgrtemp,dest,se);

    temp = flgr2dtoBinary(flgrtemp);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}


Grey_Image* MOperator::skel(Grey_Image* image,Grey_Image* out){
    Grey_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Greytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay((char*)"D", dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    do{
        for(int i=0;i<golay->nbse;i+=2){
            flgr2d_thinning(flgrtemp,dest,golay->se[i]);
            flgr2d_thinning(dest,flgrtemp,golay->se[i+1]);
        }
    }while(!(flgr2d_compare(flgrtemp,(char*)"==",dest)));

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}
Binary_Image* MOperator::skel(Binary_Image* image,Binary_Image* out){
    Binary_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* tocompare;
    FLGR_Data2D* tosub;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;

    //FLGR_Data2D* out = flgr2d_create_pixmap(img->getHeight(),img->getWidth(),1,FLGR_UINT16);
    //if(out==NULL) return NULL;*/
    //fgUINT16** pixmap = (fgUINT16**)out->array;

    dest = Binarytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay((char*)"L", dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);
    tocompare = flgr2d_create_pixmap_from(dest);
    tosub = flgr2d_create_pixmap_from(dest);

    //fgUINT16** pixmap = (fgUINT16**)golay->se[1]->array;
    //array[0][2]

    char a = '2';
    char* crtr = &a;
    flgr2d_set_data_str(golay->se[1],0,2,crtr);
    flgr2d_set_data_str(golay->se[3],2,2,crtr);
    flgr2d_set_data_str(golay->se[5],2,0,crtr);
    flgr2d_set_data_str(golay->se[7],0,0,crtr);

    do{
        flgr2d_copy(tocompare,dest);
        for(int h=0;h<10;h++){
        flgr2d_hit_or_miss(tosub,dest,golay->se[4]);
        flgr2d_arith_subsat(flgrtemp,dest,tosub);
        flgr2d_hit_or_miss(tosub,flgrtemp,golay->se[5]);
        flgr2d_arith_subsat(dest,flgrtemp,tosub);

        flgr2d_hit_or_miss(tosub,dest,golay->se[6]);
        flgr2d_arith_subsat(flgrtemp,dest,tosub);
        flgr2d_hit_or_miss(tosub,flgrtemp,golay->se[7]);
        flgr2d_arith_subsat(dest,flgrtemp,tosub);

        flgr2d_hit_or_miss(tosub,dest,golay->se[0]);
        flgr2d_arith_subsat(flgrtemp,dest,tosub);
        flgr2d_hit_or_miss(tosub,flgrtemp,golay->se[1]);
        flgr2d_arith_subsat(dest,flgrtemp,tosub);

        flgr2d_hit_or_miss(tosub,dest,golay->se[2]);
        flgr2d_arith_subsat(flgrtemp,dest,tosub);
        flgr2d_hit_or_miss(tosub,flgrtemp,golay->se[3]);
        flgr2d_arith_subsat(dest,flgrtemp,tosub);
/*
        flgr2d_thinning(flgrtemp,dest,golay->se[4]);
        flgr2d_thinning(dest,flgrtemp,golay->se[5]);
        flgr2d_thinning(flgrtemp,dest,golay->se[6]);
        flgr2d_thinning(dest,flgrtemp,golay->se[7]);
        flgr2d_thinning(flgrtemp,dest,golay->se[0]);
        flgr2d_thinning(dest,flgrtemp,golay->se[1]);
        flgr2d_thinning(flgrtemp,dest,golay->se[2]);
        flgr2d_thinning(dest,flgrtemp,golay->se[3]);*/
        }
    }while(!(flgr2d_compare(tocompare,(char*)"==",dest)));

    temp = flgr2dtoBinary(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

Grey_Image* MOperator::pruning(Grey_Image* image,Grey_Image* out,unsigned int length){
    Grey_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Greytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay((char*)"E", dest->type, FLGR_8_CONNEX);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    for(unsigned int j=0;j<length;j++)
        for(int i=0;i<golay->nbse;i+=2){
            flgr2d_thinning(flgrtemp,dest,golay->se[i]);
            flgr2d_thinning(dest,flgrtemp,golay->se[i+1]);
        }

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

Binary_Image* MOperator::pruning(Binary_Image* image,Binary_Image* out,unsigned int length){
    Binary_Image* temp;
    FLGR_Golay* golay;
    FLGR_Data2D* flgrtemp;
    FLGR_Data2D* dest;

    if(image==NULL)
        return NULL;


    dest = Binarytoflgr2d_UINT16(image);
    golay = flgr2d_create_golay((char*)"E", dest->type, FLGR_8_CONNEX);

    char a = '2';
    char* crtr = &a;
    flgr2d_set_data_str(golay->se[0],0,1,crtr);
    flgr2d_set_data_str(golay->se[2],1,2,crtr);
    flgr2d_set_data_str(golay->se[4],2,1,crtr);
    flgr2d_set_data_str(golay->se[6],1,0,crtr);

    flgr2d_set_data_str(golay->se[1],0,2,crtr);
    flgr2d_set_data_str(golay->se[3],2,2,crtr);
    flgr2d_set_data_str(golay->se[5],2,0,crtr);
    flgr2d_set_data_str(golay->se[7],0,0,crtr);

    a = '0';
    flgr2d_set_data_str(golay->se[1],1,2,crtr);
    flgr2d_set_data_str(golay->se[3],2,1,crtr);
    flgr2d_set_data_str(golay->se[5],1,0,crtr);
    flgr2d_set_data_str(golay->se[7],0,1,crtr);

    flgrtemp = flgr2d_create_pixmap_from(dest);

    flgr2d_thinning(flgrtemp,dest,golay->se[0]);
        flgr2d_thinning(dest,flgrtemp,golay->se[1]);
        flgr2d_thinning(flgrtemp,dest,golay->se[2]);
        flgr2d_thinning(dest,flgrtemp,golay->se[3]);
        flgr2d_thinning(flgrtemp,dest,golay->se[4]);
        flgr2d_thinning(dest,flgrtemp,golay->se[5]);
        flgr2d_thinning(flgrtemp,dest,golay->se[6]);
        flgr2d_thinning(dest,flgrtemp,golay->se[7]);

    temp = flgr2dtoBinary(dest);

    if(out == NULL){
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(flgrtemp);
        flgr2d_destroy(dest);
        return out;
    }
}

/*deprecated
Grey_Image* MOperator::labelling(Grey_Image* image,Grey_Image* out){
    FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;

    in = Greytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_8_CONNEX);

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;


    }
}
*/
Grey_Image* MOperator::labelling4conex(Binary_Image* image,Grey_Image* out){
    FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;

    in = Binarytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_4_CONNEX);

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;
    }
}

Grey_Image* MOperator::labelling8conex(Binary_Image* image,Grey_Image* out){
    FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;

    in = Binarytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_8_CONNEX);

    temp = flgr2dtoGrey(dest);

    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;
    }
}

Grey_Image* MOperator::areafilter(Grey_Image* image,Grey_Image* out,int threshold){
    FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;
    Grey_Image* result;
    stack<unsigned int> labels;
    unsigned int labelactive=1;
    int counter=0;

    in = Greytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_8_CONNEX);

    temp = flgr2dtoGrey(dest);

    do{
        counter=0;
        for(unsigned int i=0;i<temp->getHeight();i++)
            for(unsigned int j=0;j<temp->getWidth();j++){
                if(temp->pixelmap[i][j]==labelactive)
                    counter++;
            }
        if(counter>=threshold)
            labels.push(labelactive);
        labelactive++;
    }while(counter!=0);

    result = new Grey_Image(image->getHeight(),image->getWidth(),image->getGreyLevels());

    while(!labels.empty()){
        labelactive=labels.top();
        labels.pop();
        for(unsigned int i=0;i<temp->getHeight();i++)
            for(unsigned int j=0;j<temp->getWidth();j++){
                if(temp->pixelmap[i][j]==labelactive)
                    result->pixelmap[i][j]=image->pixelmap[i][j];
            }
    }
    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        delete temp;
        return result;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=result->pixelmap[k][l];
        delete temp;
        delete result;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;
    }
}
Binary_Image* MOperator::areafilter(Binary_Image* image,Binary_Image* out,int threshold){
    FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;
    Binary_Image* result;
    stack<unsigned int> labels;
    unsigned int labelactive=1;
    int counter=0;

    in = Binarytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_8_CONNEX);

    temp = flgr2dtoGrey(dest);

    do{
        counter=0;
        for(unsigned int i=0;i<temp->getHeight();i++)
            for(unsigned int j=0;j<temp->getWidth();j++){
                if(temp->pixelmap[i][j]==labelactive)
                    counter++;
            }
        if(counter>=threshold)
            labels.push(labelactive);
        labelactive++;
    }while(counter!=0);

    result = new Binary_Image(image->getHeight(),image->getWidth());

    while(!labels.empty()){
        labelactive=labels.top();
        labels.pop();
        for(unsigned int i=0;i<temp->getHeight();i++)
            for(unsigned int j=0;j<temp->getWidth();j++){
                if(temp->pixelmap[i][j]==labelactive)
                    result->pixelmap[i][j]=true;
            }
    }
    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        delete temp;
        return result;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=result->pixelmap[k][l];
        delete temp;
        delete result;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;
    }

}

Binary_Image* MOperator::biggerareafilter(Binary_Image* image,Binary_Image* out){
     FLGR_Data2D* in;
    FLGR_Data2D* dest;
    Grey_Image* temp;
    Binary_Image* result;
    unsigned int biggerlabel;
    unsigned int biggerarea=0;
    unsigned int labelactive=1;
    unsigned int counter=0;

    in = Binarytoflgr2d_UINT16(image);
    dest=flgr2d_create_pixmap_from(in);

    flgr2d_label(dest,in,FLGR_8_CONNEX);

    temp = flgr2dtoGrey(dest);

    do{
        counter=0;
        for(unsigned int i=0;i<temp->getHeight();i++)
            for(unsigned int j=0;j<temp->getWidth();j++){
                if(temp->pixelmap[i][j]==labelactive)
                    counter++;
            }
        if(counter>biggerarea){
            biggerlabel=labelactive;
            biggerarea=counter;
        }
        labelactive++;
    }while(labelactive<256);

    result = new Binary_Image(image->getHeight(),image->getWidth());


    labelactive=biggerlabel;
    for(unsigned int i=0;i<temp->getHeight();i++)
        for(unsigned int j=0;j<temp->getWidth();j++){
            if(temp->pixelmap[i][j]==labelactive)
                result->pixelmap[i][j]=true;
        }

    if(out == NULL){
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        delete temp;
        return result;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=result->pixelmap[k][l];
        delete temp;
        delete result;
        flgr2d_destroy(in);
        flgr2d_destroy(dest);
        return out;
    }
}


Grey_Image* MOperator::neighbourvalue(Binary_Image* img,int neighbourhood){
    Grey_Image* out = new Grey_Image(img->getHeight(),img->getWidth(),9);
    int counter;
    Position* neigh = createNeighbours();
    for(unsigned int i=0;i<img->getHeight();i++)
        for(unsigned int j=0;j<img->getWidth();j++){
            counter=0;
            if(img->pixelmap[i][j]==true)
                out->pixelmap[i][j]=counter;
            for(unsigned int k=0;k<8;k+=(8/neighbourhood))
                if(img->getPixel(Position(j,i)+neigh[k])==true)
                    counter++;
            out->pixelmap[i][j]=counter;
        }
    return out;
}

Binary_Image* MOperator::onePixelWidth(Binary_Image* img,Binary_Image* out){
    Binary_Image* temp = img->binarycopy();
    Binary_Image* tocompare = img->binarycopy();
    StructuringElement *upback = new StructuringElement(3,3);
    StructuringElement *upfore = new StructuringElement(3,3);
    StructuringElement *downback = new StructuringElement(3,3);
    StructuringElement *downfore = new StructuringElement(3,3);
    StructuringElement *leftback = new StructuringElement(3,3);
    StructuringElement *leftfore = new StructuringElement(3,3);
    StructuringElement *rightback = new StructuringElement(3,3);
    StructuringElement *rightfore = new StructuringElement(3,3);

    upback->pixelmap[0][0]=1;
    upback->pixelmap[0][1]=1;
    upback->pixelmap[1][0]=1;
    //upback->pixelmap[2][2]=1;
    upfore->pixelmap[1][1]=1;
    upfore->pixelmap[1][2]=1;
    upfore->pixelmap[2][1]=1;
    downback->pixelmap[0][0]=1;
    downback->pixelmap[1][2]=1;
    downback->pixelmap[2][1]=1;
    downback->pixelmap[2][2]=1;
    downfore->pixelmap[0][1]=1;
    downfore->pixelmap[1][0]=1;
    downfore->pixelmap[1][1]=1;
    leftback->pixelmap[0][1]=1;
    leftback->pixelmap[0][2]=1;
    leftback->pixelmap[1][2]=1;
    //leftback->pixelmap[2][0]=1;
    leftfore->pixelmap[1][0]=1;
    leftfore->pixelmap[1][1]=1;
    leftfore->pixelmap[2][1]=1;
    rightback->pixelmap[0][2]=1;
    rightback->pixelmap[1][0]=1;
    rightback->pixelmap[2][0]=1;
    rightback->pixelmap[2][1]=1;
    rightfore->pixelmap[0][1]=1;
    rightfore->pixelmap[1][1]=1;
    rightfore->pixelmap[1][2]=1;
    Binary_Image* one = new Binary_Image(img->getHeight(),img->getWidth());
    Binary_Image* two = new Binary_Image(img->getHeight(),img->getWidth());
    Binary_Image* three = new Binary_Image(img->getHeight(),img->getWidth());
    Binary_Image* four = new Binary_Image(img->getHeight(),img->getWidth());
    do{
        temp->binarycopy(tocompare);
        MOperator::hit_or_miss(temp,one,upfore,upback);
        temp->DIFFERENCE(one);
        MOperator::hit_or_miss(temp,three,rightfore,rightback);
        temp->DIFFERENCE(three);
        MOperator::hit_or_miss(temp,four,leftfore,leftback);
        temp->DIFFERENCE(four);
        MOperator::hit_or_miss(temp,two,downfore,downback);
        temp->DIFFERENCE(two);
    }while((*temp)!=tocompare);



    delete upback;
    delete upfore;
    delete downback;
    delete downfore;
    delete leftback;
    delete leftfore;
    delete rightback;
    delete rightfore;
    delete one;
    delete two;
    delete three;
    delete four;
    delete tocompare;
    if(out == NULL){
        return temp;
    }
    else{
        for(unsigned int k=0;k<out->getHeight();k++)
            for(unsigned int l=0;l<out->getWidth();l++)
                out->pixelmap[k][l]=temp->pixelmap[k][l];
        delete temp;
        return out;
    }
}
